package compte;

public class Q {
	private long num, den; // numerateur,denominateur      
	    
	public Q (long n,long d) throws Exception {
		  
		    if (d == 0) throw new Exception("Q Div 0");
		    num = n;
		    den = d;
		  }
	  public Q (long n) throws Exception {this(n,1);}

	  public double getApproximateValue() {return (((double) num) / den);}
	  public String getEntValue(){
		  return new Integer( (int)(num )).toString();
	  }
	  public long getNum() {return num;}
	  public long getDen() {return den;}

	  public Q add (Q o2) throws Exception {
		  if (den == o2.den) return new Q ( num + o2.num, den);
		  else               return new Q ( num * o2.den + den * o2.num, den * o2.den );
	  }

	  public Q sub (Q o2) throws Exception {	
		  if (den == o2.den) return new Q ( num - o2.num, den);
		  else               return new Q ( num * o2.den - den * o2.num, den * o2.den );
	  }
	  
	  public boolean equals(Q o2) { 
		long num1, den1, num2, den2;       
           num1 = num / gcd(num,den);
           den1 = den / gcd(num,den);
           num2 = o2.num / gcd(o2.num,o2.den);
           den2 = o2.den / gcd(o2.num,o2.den);
		  
		   return (num1 == num2) && (den1 == den2);
	  }
	  
	  //Modern Euclidean Algorithm
	  //1. [v = 0?] If v = 0, the algorithm terminates with u as the answer.
	  //2. [Take u mod v] Set r = u mod v, u = v, v = r, and return to step 1. 
	  //(The operations of this step decrease the value of v, but they leave gcd(u, v) unchanged.)
	  //http://www.anujseth.com/crypto/bignumbers.php
	  private long gcd(long u, long v) {
		    while (v != 0) {
		      long r = u % v; 
		      u=v;
		      v=r;  
		    }
	    	return u;
		  }

	  @SuppressWarnings("unused")
	private void reduce() {
		    long common = gcd(num,den);
		    num /= common;
		    den /= common;
      }

}
